/*
图片添加马赛克
使用方法：
ImageDoMark('dom节点或者选择器', {
	image: '图片路径',
	close: () => {
		console.log('点击了叉')
	},
	ok: image => {
		console.log("返回的base64图片是"+image);
		console.log('点击了勾');
	}
})
*/
;(function (window, document) {

	const defaultData = {
		// 根dom节点
		oElDom: null,

		// 盒子
		oMarkDom: null,

		// 视窗内容节点
		oViewContentDom: null,

		// 背景图片
		oImgDom: null,
		imgWidth: 0,
		imgHeight: 0,

		// 视图盒子
		oViewDom: null,

		// canvas
		oResultCanvas: null,
		resultContext: null,
		oDragCavnas: null,
		dragContext: null,

		// 选中操作
		nowHandle: '',
		// 操作dom
		oHandle: {
			rect: null,
			mosaic: null,
			text: null,
			back: null,
			close: null,
			ok: null,
		},

		// 文本框
		oIptBoxDom: null,
		oTextIptDom: null,

		// 图片资源
		oImage: {
			mosaic: (function() {
				var img = new Image();
				img.src = '';
				return img;
			})(),
		},

		// 鼠标数据
		mouse: {
			down: false,
			startX: 0, startY: 0,
			endX: 0, endY: 0,
			moveX: 0, moveY: 0,
			top: 0, left: 0,
		},
		iptMove: {
			down: false,
			startX: 0, startY: 0,
			moveX: 0, moveY: 0
		},

		// 画图列表
		drawList: [
			// {type: 'rect', top: 100, left: 100, width: 100, height: 50},
			// {type: 'mosaic', top: 300, left: 100, width: 100, height: 50},
			// {type: 'text', top: 200, left: 250, text: '这是一段测试文本\n这是第二段测试文本\n这是第三段'},
			// {type: 'arrow', startX: 300, startY: 100, endX: 350, endY: 200},
		]
	}

	// 总数据
	const d = {};

	const ImageDoMark = function (el, options) {
		if(!el) {
			console.log('el不能为空');
			return;
		}
		if(typeof el == 'string') {
			el = document.querySelector(el);
		}
		// 初始化数据
		initData();


		d.oElDom = el;

		// 添加内容
		initHTML(options);
		// 初始化背景
		initBgImage(options).then(function () {
			// 设置视图盒子宽高
			initViewBox();
			// 初始化canvas
			initResultCanvas();
			// 初始化拖拽绘图canvas
			initDragCanvas();
			// 绑定事件
			initEvent(options);

			doDraw();
		});
	}

	// 设置数据初始状态
	function initData() {
		for(var key in defaultData) {
			var value = defaultData[key];
			if(value && typeof value == 'object' && key != 'oImage') {
				d[key] = JSON.parse(JSON.stringify(value));
			} else {
				d[key] = value;
			}
		}
	}

	// 添加内容
	function initHTML(options) {
		var html = `<div class="image_do_mark">
				<div class="view_box">
					<div class="view_content_box">
						<canvas class="result_canvas"></canvas>
						<canvas class="drag_canvas"></canvas>
						<div class="ipt_box">
							<textarea class="text_ipt" rows="1" cols="20" autoHeight="true"></textarea>
						</div>
					</div>
				</div>
				<div class="handle_box">
	  			<div class="btn rect"></div>
	  			<div class="btn arrow">
	  				<span></span><span></span>
	  			</div>
	  			<div class="btn mosaic">
	  				<span></span>
	  				<span></span>
	  				<span></span>
	  				<span></span>
	  				<span></span>
	  			</div>
	  			<div class="btn text"></div>
	  			<div class="split"></div>
	  			<div class="btn back">
	  				<svg t="1680142368454" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7608" width="32" height="32"><path d="M482.7 249.9V106.1c0-37.4-45.3-56.2-71.7-29.7L140.3 347c-16.4 16.4-16.4 43 0 59.4L410.9 677c26.5 26.5 71.7 7.7 71.7-29.7v-155c96.1-0.3 271.5-10.7 271.5 227.7 0 118.1-92.8 216.8-216 239.6 198.1-24.4 326-236 326-361.9 0.1-292.6-309.4-346.3-381.4-347.8z" fill="" p-id="7609"></path></svg>
	  			</div>
	  			<div class="btn close">
	  				<svg t="1680143324894" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8781" width="32" height="32"><path d="M512.201 448.08L885.643 74.638c42.426-42.426 106.066 21.214 63.64 63.64L575.84 511.719l374.353 374.353c42.426 42.427-21.213 106.066-63.64 63.64L512.201 575.359 137.848 949.712c-42.426 42.426-106.066-21.213-63.64-63.64L448.563 511.72 75.12 138.278c-42.427-42.426 21.213-106.066 63.64-63.64L512.2 448.08z" p-id="8782"></path></svg>
	  			</div>
	  			<div class="btn ok">
	  				<svg t="1680143386367" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9756" width="32" height="32"><path d="M378.88 844.8 25.6 491.52 97.28 417.28 378.88 698.88 926.72 153.6 998.4 225.28Z" fill="#272636" p-id="9757"></path></svg>
	  			</div>
	  		</div>
			</div>`;
		d.oElDom.innerHTML = html;

		d.oMarkDom = d.oElDom.querySelector('.image_do_mark');
		d.oViewDom = d.oElDom.querySelector('.view_content_box');
		d.oDragCanvas = d.oElDom.querySelector('.view_box .drag_canvas');
		d.oResultCanvas = d.oElDom.querySelector('.view_box .result_canvas');
		d.oViewContentDom = d.oElDom.querySelector('.view_box .view_content_box');

		d.oHandle.rect = d.oElDom.querySelector('.handle_box .rect');
		d.oHandle.arrow = d.oElDom.querySelector('.handle_box .arrow');
		d.oHandle.mosaic = d.oElDom.querySelector('.handle_box .mosaic');
		d.oHandle.text = d.oElDom.querySelector('.handle_box .text');
		d.oIptBoxDom = d.oElDom.querySelector('.ipt_box');
		d.oTextIptDom = d.oElDom.querySelector('.text_ipt');
		d.oHandle.back = d.oElDom.querySelector('.handle_box .back');
		d.oHandle.close = d.oElDom.querySelector('.handle_box .close');
		d.oHandle.ok = d.oElDom.querySelector('.handle_box .ok');

		// 设置盒子尺寸 - 默认el的尺寸100%
		if(options.width) {
			d.oMarkDom.style.width = options.width;
		}
		if(options.height) {
			d.oMarkDom.style.height = options.height;
		}
	}

	// 初始化背景
	function initBgImage(options) {
		return new Promise(function (resolve, reject) {
			if(!options.image) {
				reject();
				return;
			}
			
			d.oImgDom = document.createElement('img');
			d.oImgDom.className = 'bg_image';
			d.oImgDom.src = options.image;
			d.oViewDom.appendChild(d.oImgDom);
			d.oImgDom.onload = function () {
				d.imgWidth = d.oImgDom.clientWidth;
				d.imgHeight = d.oImgDom.clientHeight;
				resolve();
			}
		})
	}

	// 初始化视图盒子状态
	function initViewBox() {
		d.oViewDom.style.width = d.imgWidth+'px';
		d.oViewDom.style.height = d.imgHeight+'px';
	}

	// 初始化结果canvas
	function initResultCanvas() {
		d.resultContext = d.oResultCanvas.getContext('2d');

		d.oResultCanvas.width = d.imgWidth;
		d.oResultCanvas.height = d.imgHeight;
	}

	// 初始化拖拽canvas
	function initDragCanvas() {
		
		d.dragContext = d.oDragCanvas.getContext('2d');

		d.oDragCanvas.width = d.imgWidth;
		d.oDragCanvas.height = d.imgHeight;
	}

	// 绑定事件
	function initEvent(options) {
		// 拖动 ------------------------
		
		d.oViewContentDom.addEventListener('mousedown', function (event) {
			d.mouse.startX = event.offsetX;
			d.mouse.startY = event.offsetY;
			d.mouse.moveX = 0;
			d.mouse.moveY = 0;
			if(d.nowHandle == 'text') {
				// 保存之前的数据
				setTextToList(d.mouse.top+7, d.mouse.left+7);
				// 设置新文本框位置
				d.mouse.top = d.mouse.startY - 19;
				d.mouse.left = d.mouse.startX - 7;
				setIptBoxStyle({
					display: 'block',
					top: d.mouse.top+'px',
					left: d.mouse.left+'px'
				})
				// 设置新文本框选中
				setTimeout(() => {
					d.oTextIptDom.focus();
				}, 50);
			} else {
				d.mouse.down = true;
			}
		})
		d.oViewContentDom.addEventListener('mousemove', function (event) {
			if(!d.mouse.down) {
				return;
			}
			// 清空拖拽画布
			d.oDragCanvas.width = d.oDragCanvas.width;

			// 设置终点
			d.mouse.endX = event.offsetX;
			d.mouse.endY = event.offsetY;
			// 计算开始点、结束点、宽、高
			d.mouse.moveX = event.offsetX - d.mouse.startX;
			d.mouse.moveY = event.offsetY - d.mouse.startY;
			d.mouse.top = d.mouse.moveY > 0 ? d.mouse.startY : d.mouse.startY + d.mouse.moveY;
			d.mouse.left = d.mouse.moveX > 0 ? d.mouse.startX : d.mouse.startX + d.mouse.moveX;

			// 根据不通类型画当前步骤图形
			if(d.nowHandle == 'rect') {
				// 画矩形
				drawRect(d.dragContext, d.mouse.left, d.mouse.top, Math.abs(d.mouse.moveX), Math.abs(d.mouse.moveY));
			} else if (d.nowHandle == 'arrow') {
				// 画箭头
				drawArrow(d.dragContext, d.mouse.startX, d.mouse.startY, d.mouse.endX, d.mouse.endY);
			} else if (d.nowHandle == 'mosaic') {
				// 画马赛克
				drawMosaic(d.dragContext, d.mouse.left, d.mouse.top, Math.abs(d.mouse.moveX), Math.abs(d.mouse.moveY))
			}
		})
		window.addEventListener('mouseup', function (event) {
			// 重置输入框按下
			if(d.iptMove.down) {
				d.iptMove.down = false;
				d.mouse.top = d.mouse.top+d.iptMove.moveY;
				d.mouse.left = d.mouse.left+d.iptMove.moveX;
			}

			// 重置画布按下
			if(!d.mouse.down) {
				return;
			}
			d.mouse.down = false;
			// 移动距离为0，不添加
			if(!d.mouse.moveX && !d.mouse.moveY) {
				return;
			}
			// 清空拖拽画布
			d.oDragCanvas.width = d.oDragCanvas.width;

			if(d.nowHandle == 'rect') {
				// 添加矩形到画图列表
				d.drawList.push({type: 'rect', top: d.mouse.top, left: d.mouse.left, width: Math.abs(d.mouse.moveX), height: Math.abs(d.mouse.moveY)});
			} else if (d.nowHandle == 'arrow') {
				// 添加箭头到画图列表
				d.drawList.push({type: 'arrow', startX: d.mouse.startX, startY: d.mouse.startY, endX: d.mouse.endX, endY: d.mouse.endY});
			} else if (d.nowHandle == 'mosaic') {
				// 添加马赛克到画图列表
				d.drawList.push({type: 'mosaic', top: d.mouse.top, left: d.mouse.left, width: Math.abs(d.mouse.moveX), height: Math.abs(d.mouse.moveY)});
			}
			// 确认画图形
			doDraw();
		})

		// 操作点击----------------
		// 矩形
		d.oHandle.rect.addEventListener('click', function () {
			choiceHandle(this, 'rect');
		})
		// 箭头
		d.oHandle.arrow.addEventListener('click', function () {
			choiceHandle(this, 'arrow');
		})
		// 马赛克
		d.oHandle.mosaic.addEventListener('click', function () {
			choiceHandle(this, 'mosaic');
		})
		// 文字
		d.oHandle.text.addEventListener('click', function () {
			choiceHandle(this, 'text');
		})
		// 输入框盒子
		d.oIptBoxDom.addEventListener('mousedown', function(event) {
			event.stopPropagation();
			d.iptMove.down = true;
			d.iptMove.startX = event.pageX;
			d.iptMove.startY = event.pageY;
		})
		d.oViewContentDom.addEventListener('mousemove', function(event) {
			event.stopPropagation();
			if(!d.iptMove.down) {
				return;
			}
			d.iptMove.moveX = event.pageX - d.iptMove.startX;
			d.iptMove.moveY = event.pageY - d.iptMove.startY;
			setIptBoxStyle({
				display: 'block',
				top: d.mouse.top+d.iptMove.moveY+'px',
				left: d.mouse.left+d.iptMove.moveX+'px'
			})
		})
		// 输入框
		d.oTextIptDom.addEventListener('input', function() {
		  this.style.height = 'auto';
		  this.style.height = this.scrollHeight + 'px';
		});
		d.oTextIptDom.addEventListener('mousedown', function(event) {
			event.stopPropagation();
		})
		// 倒退
		d.oHandle.back.addEventListener('click', function () {
			if(!d.drawList.length) {
				return;
			}
			// 删除最后一次操作
			d.drawList.pop();
			// 重新绘制
			doDraw();
		})
		// 关闭
		d.oHandle.close.addEventListener('click', function () {
			if(options.close) {
				options.close();
			}
		})
		// 成功
		d.oHandle.ok.addEventListener('click', function () {
			var img = new Image();
			img.src = options.image;
			img.onload = function () {
				doDraw(this, options.ok);
			}
		})
	}

	// 选中操作
	function choiceHandle(dom, type) {
		// 如果是文字，需要先保存文字
		if(d.nowHandle == 'text') {
			setTextToList(d.mouse.top+7, d.mouse.left+7);
		}
		if(hasClass(dom, 'active')) {
			delClass(dom, 'active');
			d.nowHandle = "";
			return;
		}
		handleClear();
		addClass(dom, 'active');
		d.nowHandle = type;
	}

	// 添加文字到列表，并执行绘图
	function setTextToList(top, left) {
		// 隐藏节点
		d.oIptBoxDom.style.display = 'none';
		// 判断是否有内容
		let value = d.oTextIptDom.value;
		if(!value.length) {
			return;
		}
		// 添加文字到画图列表
		d.drawList.push({type: 'text', top: top, left: left, text: d.oTextIptDom.value});
		// 置空输入框
		d.oTextIptDom.value = '';
		d.oTextIptDom.style.height = 'auto';
		// 确认画图形
		doDraw();
	}

	// 设置输入框样式
	function setIptBoxStyle(style) {
		var value = '';
		for(var key in style) {
			value += key+':'+style[key]+';'
		}
		d.oIptBoxDom.setAttribute('style', value);
	}

	// 遍历画图列表画图
	function doDraw(img, callback) {
		// 清除画布
		d.oResultCanvas.width = d.oResultCanvas.width;

		// 判断是否需要画背景图
		if(img) {
			d.resultContext.drawImage(img, 0, 0);
		}
		
		for(var i = 0; i < d.drawList.length; i++) {
			var item = d.drawList[i];
			if(item.type == 'rect') {
				drawRect(d.resultContext, item.left, item.top, item.width, item.height);
			} else if (item.type == 'arrow') {
				drawArrow(d.resultContext, item.startX, item.startY, item.endX, item.endY);
			} else if (item.type == 'mosaic') {
				drawMosaic(d.resultContext, item.left, item.top, item.width, item.height);
			} else if (item.type == 'text') {
				drawText(d.resultContext, item.left, item.top, item.text);
			}
		}
		if(callback) {
			// 生成base64图片并返回
			callback(d.oResultCanvas.toDataURL());
		}
	}

	// 画矩形
	function drawRect(ctx, x, y, width, height) {
		ctx.beginPath();
		ctx.rect(x, y, width, height);
		ctx.closePath();

		ctx.lineWidth = 3;
		ctx.fillStyle = 'rgba(255,231,41,.2)';
		ctx.strokeStyle = 'rgba(255,231,41,1)';

		ctx.fill();
		ctx.stroke();
	}

	// 画箭头
	function drawArrow(ctx, startX, startY, endX, endY) {
		ctx.lineWidth = 2;
		ctx.strokeStyle = "red";
		ctx.fillStyle = "red";
		// 绘制直线
		ctx.beginPath();
		ctx.moveTo(startX, startY);
		ctx.lineTo(endX, endY);
		ctx.stroke();

		// 绘制箭头
		const arrowSize = 10;
		const angle = Math.atan2(endY - startY, endX - startX);
		const x1 = endX - arrowSize * Math.cos(angle - Math.PI / 6);
		const y1 = endY - arrowSize * Math.sin(angle - Math.PI / 6);
		const x2 = endX - arrowSize * Math.cos(angle + Math.PI / 6);
		const y2 = endY - arrowSize * Math.sin(angle + Math.PI / 6);
		ctx.beginPath();
		ctx.moveTo(endX, endY);
		ctx.lineTo(x1, y1);
		ctx.lineTo(x2, y2);
		ctx.closePath();
		ctx.fill();
	}

	// 画马赛克
	function drawMosaic(ctx, x, y, width, height) {
		// 实际绘画宽高
		var iw = 10, ih = 10;
		// 循环绘制
		for(var i = 0; i < Math.ceil(width/iw); i++) {
			for(var j = 0; j < Math.ceil(height/ih); j++) {
				var x1 = x + i * iw; // 开始x坐标
				var y1 = y + j * ih; // 开始y坐标
				var w1 = iw, h1 = ih; // 实际绘画宽高
				if(x1-x+iw > width) {
					w1 = iw - (x1-x+iw - width);
				}
				if(y1-y+ih > height) {
					h1 = ih - (y1-y+ih - height);
				}
				ctx.drawImage(d.oImage.mosaic, 0, 0, d.oImage.mosaic.width, d.oImage.mosaic.height, x1, y1, w1, h1);
			}
		}
	}

	// 画文字
	function drawText(ctx, x, y, text) {
		let aText = text.split('\n');
		let lineHeight = 24;

		ctx.font = "bold 18px Arial";
		ctx.lineHeight = lineHeight;
		ctx.fillStyle = "red";
		ctx.textBaseline = "middle";
		for(var i = 0; i < aText.length; i++) {
			ctx.fillText(aText[i], x, y+lineHeight*i+lineHeight/2);
		}
	}

	// 删除所有操作选中
	function handleClear() {
		for(let key in d.oHandle) {
			delClass(d.oHandle[key], 'active');
		}
		d.nowHandle = '';
	}


	// 工具方法--------------------------------------------------------

	// 获取class节点
	function getByClass (className) {
		var arr = [];
		if ( document.querySelectorAll ) {
			var aElm = document.querySelectorAll('.' + className);
			for(var i=0; i<arr.length; i++) {
				arr.push(aElm[i]);
			}
		} else {
			var aElm = document.getElementsByTagName("*");
			
			for(var i=0; i<aElm.length; i++) {
				if(hasClass(aElm[i], className)) {
					arr.push(aElm[i]);
				}
			}
		}
		return arr;
	}

	// 获取节点的class列表
	function getClassList (obj) {
		var sClass = obj.className;
		var aClass = sClass.split(' ');
		var list = [];
		aClass.forEach(function (item, index) {
			if ( item ) {
				list.push(item);
			}
		})
		return list;
	}

	// 判断是否存在class
	function hasClass (obj, name) {
		var sClass = obj.className;
		var reg = new RegExp('\\b' + name + '\\b');
		if ( reg.test(sClass) ) {
			return true;
		}
		return false;
	}

	// 添加样式名
	function addClass (obj, name) {
		var hasName = hasClass(obj, name);

		if ( !hasName ) {
			var aClass = getClassList(obj);
			var sClass = '';
			aClass.push(name);

			aClass.forEach(function (item, index, arr) {
				sClass += item;
				if ( index < arr.length - 1) {
					sClass += ' ';
				}
			})

			obj.className = sClass;
		}
	}

	// 删除样式名
	function delClass (obj, name) {
		var hasName = hasClass(obj, name);

		if ( hasName ) {
			var sClass = obj.className;
			var arr = sClass.split(name);
			sClass = '';
			arr.forEach(function (item) {
				sClass += item;
			})
			sClass = sClass.replace(/\s+/g, ' ');
			sClass = sClass.replace(/^\s|\s$/g, '');
			obj.className = sClass;
		}
	}

	window.ImageDoMark = ImageDoMark;
})(window, document);